#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "plst.h"
#include "/windows/D/svn/preplayer/engine_cpp/adaptors.h"
#include <QFile>
#define  Qconnect QObject::connect

void MainWindow::init_eq(void)
{
    eq = new Equalizer(this);
    eq->setAllowedAreas(Qt::AllDockWidgetAreas);
    addDockWidget(Qt::RightDockWidgetArea, eq, Qt::Horizontal);
    Qconnect(eq, SIGNAL(update_channels()), this, SLOT(slot_set_eq()));
}

void MainWindow::init_vis(void)
{
   // qDebug("file __FILE__ line __LINE__");
    visualizator = NULL;
   // visualizator = new vis_draw(this);
    //visualizator->setAllowedAreas(Qt::AllDockWidgetAreas);
    //addDockWidget(Qt::TopDockWidgetArea, visualizator, Qt::Horizontal);
   // Qconnect(&dr_timer, SIGNAL(timeout()), this, SLOT(slot_repaint(void)));

}
#define DEBUG
#define NO_ENGINE
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
	qDebug("MainWindow:: constructor");

    hndl = 0;
    MYFFT_LEN = 1024;
    MYWAVE_LEN = 2048;
    mywave = NULL;
    myfft = NULL;
    playb_sliding = false;
    if (!engine_init())
    {
        qDebug("can`t initilize audio-engine...");
        qDebug("Current Audio engine:BASS");
        abort();
    }
    ui->setupUi(this);
    init_playlist();
    init_connections();
    init_timers();
    init_eq();
    init_vis();
    slot_volume();
    paused = false;
#ifdef PLAY_DEBUG
    playlist->add_fileqs("/windows/D/Music/b.ogg");
    slot_play();
#endif
    qDebug("MainWindow:: constructor end");
}


void MainWindow::init_timers(void)
{
	qDebug("MainWindow:: init_timers");
    pl_timer.setInterval(1000);
    dr_timer.setInterval(33);
    qDebug("MainWindow:: init_timers end");
}

void MainWindow::init_playlist(void)
{
	qDebug("MainWindow:: init_playlist");
    playlist = new plst(NULL);
    playlist->show();
    centralWidget()->layout()->addWidget(playlist);
    qDebug("MainWindow:: init_playlist end");

}

void MainWindow::init_connections(void)
{
	qDebug("MainWindow:: init_connections");
    Qconnect(ui->btn_play, SIGNAL(clicked()),this, SLOT(slot_play(void)));
    Qconnect(ui->btn_stop, SIGNAL(clicked()),this, SLOT(slot_stop(void)));
    Qconnect(ui->btn_pause, SIGNAL(clicked()), this, SLOT(slot_pause(void)));
    Qconnect(ui->btn_Add, SIGNAL(clicked()), playlist, SLOT(slot_file_add(void)));
    Qconnect(ui->btn_prev, SIGNAL(clicked()), this, SLOT(slot_play_prev(void)));
    Qconnect(ui->btn_nxt, SIGNAL(clicked()), this, SLOT(slot_play_next(void)));
    Qconnect(ui->volume_slider, SIGNAL(sliderMoved(int)), this, SLOT(slot_volume(void)));
    Qconnect(ui->volume_slider, SIGNAL(sliderPressed()), this, SLOT(slot_volume(void)));
    Qconnect(ui->volume_slider, SIGNAL(sliderReleased()), this, SLOT(slot_volume(void)));
    Qconnect(ui->time_slider, SIGNAL(sliderMoved(int)), this, SLOT(slot_pos_move(void)));
    Qconnect(ui->time_slider, SIGNAL(sliderPressed()), this, SLOT(slot_slide_start(void)));
    Qconnect(ui->time_slider, SIGNAL(sliderReleased()), this, SLOT(slot_slide_stop(void)));
    Qconnect(&pl_timer, SIGNAL(timeout()), this, SLOT(slot_playb_timer(void)));
    Qconnect(playlist, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(slot_plst_dblclk(QListWidgetItem*)));
    Qconnect(ui->actionFile, SIGNAL(activated()), playlist, SLOT(slot_file_add(void)));
    Qconnect(ui->actionFileO, SIGNAL(activated()), playlist, SLOT(slot_file_open(void)));
    Qconnect(ui->actionFolder, SIGNAL(activated()), playlist, SLOT(slot_dir_add(void)));
    Qconnect(ui->actionFolderO, SIGNAL(activated()), playlist, SLOT(slot_dir_open(void)));
    Qconnect(ui->actionPlaylist, SIGNAL(activated()), playlist, SLOT(slot_playlist_add(void)));
    Qconnect(ui->actionPlaylistO, SIGNAL(activated()), playlist, SLOT(slot_playlist_open(void)));
    Qconnect(ui->actionSave_Playlist, SIGNAL(activated()), playlist, SLOT(slot_playlist_save(void)));
    qDebug("MainWindow:: init_playlist end");
}

void MainWindow::keyReleaseEvent(QKeyEvent *e)
{
	qDebug("MainWindow:: keyReleaseEvent");
    qDebug("key code pressed %d",e->key());
    switch(e->key())
    {
        case Qt::Key_Space: slot_pause(); break;
        case Qt::Key_Delete :playlist->delete_selected(); break;
        case Qt::Key_Enter: slot_play();
    }
    qDebug("MainWindow:: keyReleaseEvent end");
}

//--------------------------------------------SLOTS---------------------------------
//----------------------------------------------PLAYBACK SLOTS--------------------------------------------
void MainWindow::slot_pause(void)
{
	qDebug("MainWindow:: slot_pause");
    if (hndl)
    {
        if (paused)
            engine_channel_play(hndl, false);
        else
            engine_channel_pause(hndl);
        paused = !paused;
    }
    qDebug("MainWindow:: slot_pause end");
}

void MainWindow::slot_play(void)
{
	qDebug("MainWindow:: slot_play");
    play(playlist->get_file_name());
    qDebug("MainWindow:: slot_play end");
}


void MainWindow::slot_stop(void)
{
	qDebug("MainWindow:: slot_stop");
    if (pl_timer.isActive())
        pl_timer.stop();
    if (dr_timer.isActive())
        dr_timer.stop();
    ui->time_slider->setValue(0);
    if (hndl)
        engine_channel_terminate(hndl);
    hndl = 0;
    MainWindow::setWindowTitle("preplayer 0.001");
    qDebug("MainWindow:: slot_stop end");
}
//--------------------------------------------PLaylist------------------------------------

void MainWindow::slot_plst_dblclk(QListWidgetItem *item)
{
	qDebug("MainWindow:: slot_plst_dblclk");
    //char *str =  playlist->get_file_name();
    play(playlist->get_file_name());
    qDebug("MainWindow:: slot_plst_dblclk end");
}

//-----------------------------------SLIDERS----------------------------------------------
void MainWindow::slot_volume(void)
{
	qDebug("MainWindow:: slot_volume");
    qDebug("Change volume %d", ui->volume_slider->sliderPosition());
    char str[512];
    sprintf(str, "Volume changed %d %%",ui->volume_slider->sliderPosition());
    MainWindow::setWindowTitle(str);
    float vl = float(ui->volume_slider->sliderPosition()) / 100;
    engine_set_volume(vl);
    qDebug("MainWindow:: slot_volume end");
}

void MainWindow::slot_pos_move(void)
{
	qDebug("MainWindow:: slot_pos_move");
    if (!playb_sliding && hndl)
    {
        unsigned long long pos = engine_channel_seconds2bytes(hndl, ui->time_slider->value());
        engine_channel_setposition(hndl, pos, ENGINE_POS_BYTE);
        playb_sliding = false;
    }
    qDebug("MainWindow:: slot_pos_move end");
}

void MainWindow::slot_slide_start()
{
	qDebug("MainWindow:: slot_slide_start");
    pl_timer.stop();
    playb_sliding = true;
    qDebug("MainWindow:: slot_slide_start end");
}

void MainWindow::slot_slide_stop()
{
	qDebug("MainWindow:: slot_slide_stop");
    playb_sliding = false;
    slot_pos_move();
    pl_timer.start();
    qDebug("MainWindow:: slot_slide_stop end");
}


//---------------------------------------TIMER--------------------------------------------------------------


void MainWindow::slot_playb_timer(void)
{
	qDebug("MainWindow:: slot_playb_timer");
    if (playb_sliding)
        return;
    int time_val = ui->time_slider->value();
    ui->time_slider->setValue(floor(engine_channel_bytes2seconds(hndl, engine_channel_getposition(hndl, ENGINE_POS_BYTE))));
    //unsigned sz = floor(log(ui->time_slider->value() + 2)) + 1;
    char ch[512];
    sprintf(ch, "CPU: %.2f%%; time %2d:%2d//%2d:%2d", engine_get_cpu(), ui->time_slider->value() / 60,
                         ui->time_slider->value() % 60, ui->time_slider->maximum() / 60, ui->time_slider->maximum()% 60);
    if (time_val == ui->time_slider->maximum())
    {
        slot_stop();
        slot_play_next();
    }
    MainWindow::setWindowTitle(ch);
    qDebug("MainWindow:: slot_playb_timer end");
}
///--------------------------------------------------------END------------OF-----------SLOTS---------------------------------
///--------------------------NEXT------------------AND-----------PREV--------------------------------------------------------
char *mystrcopy(const char *s)
{
   char * res = NULL;
   int len = strlen(s);
   res = new char[len + 2];
   strncpy(res, s, strlen(s) + 2);
   res[len + 1] = 0;

   return res;
}

bool str_test(char *str)//detect encoding of str
{
    QString qstr = "";
    QFileInfo finfo;
    qstr = QString::fromAscii(str);
    finfo.setFile(qstr);
    if (finfo.exists())
        return true;

    qstr = QString::fromLatin1(str);
    finfo.setFile(qstr);
    if (finfo.exists())
        return true;

    qstr = QString::fromUtf8(str);
    finfo.setFile(qstr);
    if (finfo.exists())
        return true;

    qstr = QString::fromLocal8Bit(str);
    finfo.setFile(qstr);
    if (finfo.exists())
        return true;

    return false;
}

void MainWindow::play(QString str)
{
	qDebug("MainWindow:: play");
    if (str.isEmpty() || str.isNull())
        return;
    this->slot_stop();

    char *fnameascii, *fnameutf8, *fnamelocal8bit, *fnamelatin1;
    int len = str.length();
    fnameascii = mystrcopy(str.toAscii().data());
    fnameutf8 = mystrcopy(str.toUtf8().data());
    fnamelocal8bit = mystrcopy(str.toLocal8Bit().data());
    fnamelatin1 = mystrcopy(str.toLatin1().data());
    char *fname;

    if (str_test(fnameascii))
       fname = fnameascii;
    else
        if (str_test(fnameutf8))
            fname = fnameutf8;
        else
            if (str_test(fnamelocal8bit))
               fname = fnamelocal8bit;
            else
                if (str_test(fnamelatin1))
                  fname = fnamelatin1;

    hndl = engine_channel_create(fname, 0);
    for (int i = 0; i < EQS_MAX; i++)
        engine_equalizer_init(hndl, eq->_fxs[i]);
    if (!hndl)// All things are bad die
        return;
    ui->time_slider->setMaximum(floor(engine_channel_getlength(hndl)));
    if (pl_timer.interval() != 0)
        pl_timer.start();
    if (!mywave)
        mywave = new unsigned[MYWAVE_LEN];
    if (!myfft)
        myfft = new float[MYFFT_LEN];

    if (visualizator)
        visualizator->init(mywave, myfft, MYWAVE_LEN, MYFFT_LEN);
    if (dr_timer.interval() != 0)
        dr_timer.start();

    delete [] fnameascii;
    delete [] fnameutf8;
    delete [] fnamelocal8bit;
    delete [] fnamelatin1;
    qDebug("MainWindow:: play end");
}


void MainWindow::slot_play_next(void)
{
	qDebug("MainWindow:: slot_play_next");
    slot_stop();
    int id = playlist->currentRow();
    if (ui->rnchk->checkState())
        id =  rand() % playlist->count();
    else
        if (ui->cycle_chk->checkState())
            id = (id + 1) % playlist->count();
        else
            if (id < (playlist->count() - 1))
                id++;
            else
                return;
    play(playlist->get_file_byid(id));
    playlist->setCurrentRow(id);
    qDebug("MainWindow:: slot_play_next end");
}

void MainWindow::slot_set_eq(void)
{
    for (int i = 0; i < EQS_MAX; i++)
        engine_equalizer_setfreq(eq->_fxs[i], eq->eqs[i]->hz, eq->eqs[i]->val);
}


void MainWindow::slot_play_prev(void)
{
	qDebug("MainWindow:: slot_play_prev");
    int id = playlist->currentRow();
    if (ui->rnchk->checkState())
        id =  rand() % playlist->count();
    else
        if (ui->cycle_chk->checkState())
            id = (playlist->count() + id - 1) % playlist->count();
        else
            if (id > 0)
                id--;
            else
                return;
    play(playlist->get_file_byid(id));
    playlist->setCurrentRow(id);
    qDebug("MainWindow:: slot_play_prev end");
}

void MainWindow::slot_repaint(void)
{
    qDebug("MainWindow:: slot_repaint");
    engine_channel_getdata(hndl, mywave, MYWAVE_LEN);
    engine_channel_getdata(hndl, myfft, ENGINE_FFT1024);
    visualizator->d_repaint();
    qDebug("MainWindow:: slot_repaint end");
}
//-----------------------------------------------DESTRUCTOR----------------------------------------------------
MainWindow::~MainWindow()
{
	qDebug("MainWindow:: destructor");
    engine_free_allplugins();
    engine_free();
    delete ui;
    if (playlist)
        delete playlist;
    if (eq)
        delete eq;
    if (visualizator)
        delete visualizator;
    qDebug("MainWindow:: destructor end");
}
